﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace Xceed.Silverlight.Data
{
  internal sealed class DataSourceContext
  {
    #region Constructors

    internal DataSourceContext(
      DataSourceGroupContext groupContext,
      DataSourceSortContext sortContext,
      DataSourceFilterContext filterContext,
      IEnumerable<SortDescription> primaryKeys )
    {
      if( groupContext == null )
        throw new ArgumentNullException( "groupContext" );

      if( sortContext == null )
        throw new ArgumentNullException( "sortContext" );

      if( filterContext == null )
        throw new ArgumentNullException( "filterContext" );

      if( primaryKeys == null )
        throw new ArgumentNullException( "primaryKeys" );

      if( !primaryKeys.Any() )
        throw new ArgumentException( "A primary key is required.", "primaryKeys" );

      m_groupContext = groupContext;
      m_sortContext = sortContext;
      m_filterContext = filterContext;
      m_primaryKeys = primaryKeys.ToList().AsReadOnly();
    }

    internal DataSourceContext(
      GroupHandler groupHandler,
      SortingHandler sortHandler,
      FilteringHandler filterHandler,
      IEnumerable<SortDescription> primaryKeys )
      : this(
        new DataSourceGroupContext( groupHandler ),
        new DataSourceSortContext( sortHandler ),
        new DataSourceFilterContext( filterHandler ),
        primaryKeys )
    {
    }

    private DataSourceContext( DataSourceContext copy )
      : this(
        copy.GroupContext.Clone(),
        copy.SortContext.Clone(),
        copy.FilterContext.Clone(),
        copy.PrimaryKeys )
    {
    }

    #endregion

    #region FilterContext Property

    internal DataSourceFilterContext FilterContext
    {
      get
      {
        return m_filterContext;
      }
    }

    private readonly DataSourceFilterContext m_filterContext;

    #endregion

    #region GroupContext Property

    internal DataSourceGroupContext GroupContext
    {
      get
      {
        return m_groupContext;
      }
    }

    private readonly DataSourceGroupContext m_groupContext;

    #endregion

    #region SortContext Property

    internal DataSourceSortContext SortContext
    {
      get
      {
        return m_sortContext;
      }
    }

    private readonly DataSourceSortContext m_sortContext;

    #endregion

    #region PrimaryKeys Property

    internal IList<SortDescription> PrimaryKeys
    {
      get
      {
        return m_primaryKeys;
      }
    }

    private readonly IList<SortDescription> m_primaryKeys;

    #endregion

    public override int GetHashCode()
    {
      int hashCode = 11;

      hashCode += 17 * this.FilterContext.GetHashCode();
      hashCode += 17 * this.GroupContext.GetHashCode();
      hashCode += 17 * this.SortContext.GetHashCode();

      return hashCode;
    }

    public override bool Equals( object obj )
    {
      if( object.ReferenceEquals( obj, this ) )
        return true;

      DataSourceContext context = obj as DataSourceContext;

      if( object.ReferenceEquals( context, null ) )
        return false;

      if( context.GetHashCode() != this.GetHashCode() )
        return false;

      return ( object.Equals( context.FilterContext, this.FilterContext ) )
          && ( object.Equals( context.GroupContext, this.GroupContext ) )
          && ( object.Equals( context.SortContext, this.SortContext ) )
          && ( context.PrimaryKeys.SequenceEqual( this.PrimaryKeys ) );
    }

    internal DataSourceContext Clone()
    {
      return new DataSourceContext( this );
    }

    internal IEnumerable<SortDescription> GetCurrentSortOrder()
    {
      return DataUtils.GetSortOrder(
        this.GroupContext.GroupNames,
        this.SortContext.SortDescriptions,
        Enumerable.Empty<SortDescription>() );
    }

    internal IEnumerable<SortDescription> GetCurrentCompleteSortOrder()
    {
      return DataUtils.GetSortOrder(
        this.GroupContext.GroupNames,
        this.SortContext.SortDescriptions,
        this.PrimaryKeys );
    }
  }
}
